﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using System.Data;

namespace ToolsCXml
{
    public delegate bool BoolCondition(string s);
    public delegate string ActCondition(string s);   
    public class BETag
    {
        public BETag(string s ) 
        {
            OK = false;
            if (s == null)
                return;
            if (s.StartsWith("{"))
            {
                BEPos bp = BETag.FormatCmd(s, '{', '}');
                if (bp.Valid())
                {
                    Cmd = new Cmd( bp.String);//////////???????   
                    s = s.Substring(bp.E + 1);
                }
            }
            string[] items = s.Split(new string[] { "[", "]", "-" }, StringSplitOptions.RemoveEmptyEntries);
            if (items.Length == 2)
            {
            	Begin = items[0].Replace("@@##","[").Replace("##@@","]").Replace("@@", "-");
            	End = items[1].Replace("@@##","[").Replace("##@@","]").Replace("@@", "-");
            }
            else if (items.Length == 1)
            {
                Begin = items[0].Replace("@@##","[").Replace("##@@","]").Replace("@@", "-");
                End = "";
            }
            else
                return;
            OK = true;
        }
        public BEPos BEPos(string s)
        {
            if (OK)
            {
                int B = s.IndexOf(Begin);
                if (B != -1)
                {
                    B = B + Begin.Length;
                    int E = s.IndexOf(End, B);
                    if (E != -1) 
                        return new BEPos(B, E, s);
                }
            }
            return new BEPos(-1, -1, s);
        }
        public BEPos BEPos(BEPos bp)//ReverseMatch
        {
            string s = bp.InnerStr;
            if(!OK || s==null || !bp.Valid())
                return new BEPos(-1, -1, s);
          
            int B = s.IndexOf(Begin, bp.B);
            if(Cmd!=null && Cmd.ReverseMatch)
                B = s.LastIndexOf(Begin, bp.B,bp.E-bp.B);
            if (B != -1 && B<bp.E)
            {
                B = B + Begin.Length;
                int E = s.IndexOf(End, B, bp.E - B);
                if (E != -1)
                    return new BEPos(B, E, s);
            }

            B = s.LastIndexOf(Begin, bp.E, bp.E - bp.B);
            if (B != -1)
            {
                B = B + Begin.Length;
                int E = s.IndexOf(End, B, bp.E - B);
                if (E != -1)
                    return new BEPos(B, E, s);
            }
            return new BEPos(-1, -1, s);          
        }          
        public BEPos NextBEPos(BEPos bp) //同一个才能NextBEPos
        {
            string s = bp.InnerStr;
            if(!OK || !bp.Valid() || s==null )
                return new BEPos(-1, -1, s);
            int B = s.IndexOf(Begin,bp.E+End.Length);          
            if (B == -1) 
                return new BEPos(-1, -1, s);
            B = B + Begin.Length;
            int E = s.IndexOf(End, B);
            if (E == -1) 
                return new BEPos(-1, -1, s);
            return new BEPos(B, E, s);
        }
        public static BEPos FormatCmd(string Rule, char begin, char end,int startIndex=0 )
        {
            int B = 0;
            int Pos = Rule.IndexOfAny(new char[] { begin, end },startIndex);
            if (Pos != -1 && Rule[Pos] == begin)
            {
                B = Pos+1;
                int stack = 1;
                while (Pos != -1)
                {
                    Pos = Rule.IndexOfAny(new char[] { begin, end }, Pos + 1); //??
                    if (Rule[Pos] == begin)
                        stack++;
                    else if (Rule[Pos] == end)
                        stack--;
                    if (stack == 0)
                        return new BEPos(B, Pos, Rule);
                    if (stack < 0)
                        break;
                }
            }
            return new BEPos(-1, -1, Rule);
        }
        public string Begin { get; set; }
        public string End { get; set; }
        public Cmd Cmd{get;set;}
        public Boolean OK{get;set;}

        public override string ToString()
        {
            if(Cmd ==null)
            return "["+Begin.Replace("-","@@")+"-"+End.Replace("-","@@") +"]";
            else
            return "["+Cmd.ToString()+Begin.Replace("-","@@")+"-"+End.Replace("-","@@") +"]";
        }
    }
    public class BETags
    {
        public BETags(List<BETag> rbts)
        {
            this.tags = rbts;
        }
        public BETags(string Rule)
        {
            tags = new List<BETag>();
            BEPos bp;
            if (Rule.StartsWith("{"))
            {
                bp = BETag.FormatCmd(Rule, '{', '}');
                if (bp.Valid())
                {
                    string cmdstr = bp.String;/////////////////////////////////
                    this.Cmd = new Cmd(cmdstr);
                    Rule = Rule.Substring(bp.E + 1);
                }
            }
            //Compute Rule
            bp =  BETag.FormatCmd(Rule, '[', ']', 0);
            while (bp.Valid())
            {
                BETag bt = new BETag(bp.String);
                if(bt.OK)
                tags.Add(bt);
                bp = BETag.FormatCmd(Rule, '[', ']', bp.E + 1);
            }
            //Compute Cmd
        }
        public void Add(BETag bt)
        {
            tags.Add(bt);
        }
        public BETags SubTags(int b,int length=-1)
        {
            List<BETag> rbts = new List<BETag>();
            if(b>=0)
            for (int i = b, len = 0; i < tags.Count && len!=length; i++, len++)
                rbts.Add(tags[i]);
            return new BETags(rbts);
        }
        public List<BETag> tags{get;set;}

        public Cmd Cmd { get; set; }

        public string Match(string txt)
        {
            BEPos bp = null;
            if(tags.Count>0)
                bp = tags[0].BEPos(txt);
            for (int i = 1; i < tags.Count; i++)
                bp = tags[i].BEPos(bp);
            if (bp == null)
                return "";
            return bp.String;
        }
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder("tags=");
            foreach (BETag bt in tags)
                sb.Append(bt.ToString());
            if(Cmd!=null)
            sb.Append(" cmd=" + Cmd.ToString());
            return sb.ToString();
        }
    }
    public class BEPos
    {
        public BEPos() 
        {
            str = null;
            B = -1; 
            E = -1;
        }
        public BEPos(int b, int e, string str)
        {
            this.str = str;
            B = b;
            E = e;
        }
        public bool Valid()
        {
            return B > -1 && str!=null  && ( E > -1 && B<E || E==-1);
        }
        public string String { get {
            if (!Valid()) return "";
            return str.Substring(B, E==-1?-1: E - B);
        } }
        public int B { get; set; }
        public int E { get; set; }
        public string InnerStr { get { return str; } }
        private  string str;
    }
    public class BEId
    {
        public BEId()
        {
            B = E =activeindex= -1;
        }
        public void MoveNext()
        {
            activeindex++;
        }
        public void MoveToTop()
        {
            activeindex=0;
        }
        public bool OK()
        {
            return B > 0 && E > 0 && B < E;
        }
        public bool HasNext
        {
            get
            {
                return activeindex>=0 && activeindex <E-B;
            }
        }
        public int B { get; set; }
        public int E { get; set; }
        public int ActiveIndex { get { return activeindex+B; } }
        private int activeindex;
    }
    public class FieldSet
    {
        public FieldSet(string Name, string ValueType, string Rule)
        {
            this.Name = Name;
            this.ValueType = ValueType;
            this.BETags = new BETags(Rule);
        }
        public string Name { get; set; }
        public string ValueType { get; set; }
        public BETags BETags { get; set; }
        internal string GetValue(string txt,CItem item)
        {
            string retstr = BETags.Match(txt);
            if (BETags.Cmd != null)
            {
                
                if (BETags.Cmd.TxtAsUrl)
                {                    
                    GetCorrectUrl(item.Url, ref  txt);
                    if (DgvTools.ValidUrl(txt))
                    {
                        CWeb web = CItem.web;
                        txt = web.GetOKUrl(txt);
                        retstr = BETags.Match(txt);
                    }
                }
                if(BETags.Cmd.ModeAllTxt)
                	return txt;
                if (BETags.Cmd.tablevalueCmd != null)
                {
                    if(BETags.Cmd.tablevalueCmd.Valid)
                        retstr = BETags.Cmd.tablevalueCmd.GetValue();
                }
                if (BETags.Cmd.gapvalueCmd  != null)
                {
                	if(BETags.Cmd.gapvalueCmd.Valid){
                        retstr = BETags.Cmd.gapvalueCmd.GetValue();
                        if(BETags.tags.Count>0)
                        retstr = BETags.Match(retstr);
                	}
                }
                if (BETags.Cmd.ReplaceTemplate != null)
                {
                    retstr = BETags.Cmd.ReplaceTemplate.Replace("[" + Name + "]", retstr);
                }
                if (BETags.Cmd.NextUrlTags != null)
                {
                    CWeb web = CItem.web;
                    BETags Nu = BETags.Cmd.NextUrlTags;
                    string str = "";
                    StringBuilder sb = new StringBuilder("");
                    while (true)
                    {
                        if (!txt.Contains(BETags.Cmd.NextExist))
                            break;
                        string url = Nu.Match(txt);
                        GetCorrectUrl(item.Url, ref  url);
                        txt = web.GetOKUrl(url);
                        str = BETags.Match(txt);
                        if (BETags.Cmd.ReplaceTemplate != null)
                        {
                            str = BETags.Cmd.ReplaceTemplate.Replace("[" + Name + "]", str);
                        }
                        sb.Append(str);
                    }
                    retstr += sb;
                }
                if (BETags.Cmd.ReplacetoNullTags != null)
                {
                    foreach (BETag t in BETags.Cmd.ReplacetoNullTags.tags)
                        retstr = retstr.Replace(t.Begin, t.End);
                }
                if (BETags.Cmd.caseCmd != null)
                {
                    //compute N=

                    foreach (Condition c in BETags.Cmd.caseCmd.conditions)
                    {
                        if (c.b(retstr))
                        {
                            retstr = c.a(retstr);
                            break;
                        }
                    }
                }
            }
            return retstr;
        }

        private static void GetCorrectUrl(string UrlTemplate,ref string url)
        {
            if (DgvTools.ValidUrl(url) && !url.StartsWith("http://"))
            {
                if (url.Contains("/"))
                {
                    string[] paths = url.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
                    foreach (string s in paths)
                    {
                        if (UrlTemplate.Contains(s))
                        {
                            url = UrlTemplate.Substring(0, UrlTemplate.LastIndexOf("/" + s)) + url;
                            break;
                        }
                    }
                }
            }
        }
    }
    public class Cmd
    {
        public Cmd(string str)
        {
            ListTable = new List<TableCmd>();
            ListGap  = new List<SubGapCmd>();
            ReverseMatch = false;
            TxtAsUrl = false;
            ModeAllTxt = false;
            string[] items = str.Split(new string[] { ";\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            cmdkeyvalue = new Dictionary<string, string>();
            foreach (string s in items)
            {
                if (s.Contains("="))
                {
                    string name = s.Substring(0, s.IndexOf('=')).Trim();
                    if (DgvTools.ValidName(name) && !cmdkeyvalue.ContainsKey(name))
                        cmdkeyvalue[name] = s.Substring(s.IndexOf('=') + 1);
                }
            }
            string keyname = "";
            if (cmdkeyvalue.ContainsKey("nexturl"))
                NextUrlTags = new BETags(cmdkeyvalue["nexturl"]);
            if (cmdkeyvalue.ContainsKey("nextexist"))
                NextExist = cmdkeyvalue["nextexist"];
            if (cmdkeyvalue.ContainsKey("replacetemplate"))
            {
                ReplaceTemplate = cmdkeyvalue["replacetemplate"];
                ReplaceTemplate = ReplaceTemplate.Replace("\\r\\n", "\r\n")
                    .Replace("\\t", "\t");
            }
            if (cmdkeyvalue.ContainsKey("replacetonull"))
            {
                ReplacetoNullTags = new BETags(cmdkeyvalue["replacetonull"]);
            }
            if (cmdkeyvalue.ContainsKey("multisubitem"))
                MultiSubItemTags = new BETags(cmdkeyvalue["multisubitem"]);
            if (cmdkeyvalue.ContainsKey("reversematch"))
            {
                if (cmdkeyvalue["reversematch"] == "true")
                    ReverseMatch = true;
            }
            if (cmdkeyvalue.ContainsKey("txtasurl"))
            {
                if (cmdkeyvalue["txtasurl"] == "true")
                    TxtAsUrl = true;
            }
            if (cmdkeyvalue.ContainsKey("dbidbeginend"))
            {
               BETags bts = new BETags(cmdkeyvalue["dbidbeginend"]);
               Bedbid = null;
               if (bts.tags.Count == 1 && DgvTools.ValidNumber(bts.tags[0].Begin)
                                       && DgvTools.ValidNumber(bts.tags[0].End))
               {
                   Bedbid = new BEId();
                   Bedbid.B = Convert.ToInt32(bts.tags[0].Begin);
                   Bedbid.E = int.MaxValue;
                   if (DgvTools.ValidNumber(bts.tags[0].End))
                       Bedbid.E = Convert.ToInt32(bts.tags[0].End);                  
                   Bedbid.MoveToTop();
               }//else 未设置BeDbid
            }
            if (cmdkeyvalue.ContainsKey("savepath"))
                SavePath = cmdkeyvalue["savepath"];
            DownLoadSuburlType = "auto";
            if (cmdkeyvalue.ContainsKey("downloadsuburl"))
            {
                string downloadsuburl = cmdkeyvalue["downloadsuburl"];
                if (downloadsuburl.ToLower().Trim() == "true")
                {
                    DownLoadSuburl = true;
                    DownLoadSuburlType = "auto";
                    if (cmdkeyvalue.ContainsKey("downloadsuburltype"))
                        DownLoadSuburlType = cmdkeyvalue["downloadsuburltype"].Trim();
                    DownLoadSuburlChangeUrl = false;                    
                    if (cmdkeyvalue.ContainsKey("downloadsuburlchangeurl")
                        && cmdkeyvalue["downloadsuburlchangeurl"].Trim().ToLower()=="true")
                        DownLoadSuburlChangeUrl = true;
                }
            }

            keyname = "downloadurl";
            DownLoadurlType = "auto";
            if (cmdkeyvalue.ContainsKey(keyname))
            {
                string value = cmdkeyvalue["downloadurl"];
                if (value.ToLower().Trim() == "true")
                {
                    DownLoadurl = true;
                    DownLoadurlType = "auto";
                    keyname = "downloadurltype";
                    if (cmdkeyvalue.ContainsKey(keyname))
                        DownLoadurlType = cmdkeyvalue[keyname].Trim();
                    DownLoadurlChangeUrl = false;

                    keyname = "downloadurlchangeurl";
                    if (cmdkeyvalue.ContainsKey(keyname)
                        && cmdkeyvalue[keyname].Trim().ToLower() == "true")
                        DownLoadurlChangeUrl = true;
                }
            }

            keyname = "location";
            if (cmdkeyvalue.ContainsKey(keyname))
            {
                bLocation = false;
                string value = cmdkeyvalue["downloadurl"];
                if (value.ToLower().Trim() == "true")
                {
                    bLocation = true;
                }
            }
            if (cmdkeyvalue.ContainsKey("casecmd"))
            {
                BEPos bp = BETag.FormatCmd(cmdkeyvalue["casecmd"], '{', '}');
                if (bp.Valid())
                {
                    string cmdstr = bp.String;
                    caseCmd = new CaseCmd(cmdstr);                    
                }
            }
            if (cmdkeyvalue.ContainsKey("table"))
            {
                BEPos bp = BETag.FormatCmd(cmdkeyvalue["table"], '{', '}');
                if (bp.Valid())
                {
                    string tablecmdstr = bp.String;
                    tableCmd = new TableCmd(tablecmdstr);
                    ListTable.Add(tableCmd); // 以后可以添加多个Table
                }
            }
            if (cmdkeyvalue.ContainsKey("tablevalue"))
            {
                BEPos bp = BETag.FormatCmd(cmdkeyvalue["tablevalue"], '{', '}');
                if (bp.Valid())
                {
                    string tablecmdstr = bp.String;
                    tablevalueCmd = new TableValueCmd(tablecmdstr);
                    
                }
            }
            if(cmdkeyvalue.ContainsKey("mode")){
            	string s = cmdkeyvalue["mode"];
            	if(s=="alltxt")
            		ModeAllTxt = true;
            }
            if (cmdkeyvalue.ContainsKey("subgap"))
            {
                BEPos bp = BETag.FormatCmd(cmdkeyvalue["subgap"], '{', '}');
                if (bp.Valid())
                {
                    string tablecmdstr = bp.String;
                    subgapCmd = new SubGapCmd(tablecmdstr);
                    ListGap.Add(subgapCmd); // 以后可以添加多个Table
                }
            }
            if (cmdkeyvalue.ContainsKey("gapvalue"))
            {
                BEPos bp = BETag.FormatCmd(cmdkeyvalue["gapvalue"], '{', '}');
                if (bp.Valid())
                {
                    string tablecmdstr = bp.String;
                    gapvalueCmd = new GapValueCmd(tablecmdstr);
                    
                }
            }
        }
        private Dictionary<string, string> cmdkeyvalue;
        public BETags MultiSubItemTags { get; set; }
        public BETags NextUrlTags { get; set; }
        public BETags ReplacetoNullTags { get; set; }

        public bool TxtAsUrl { get; set; }
        public bool ReverseMatch { get; set; }
        public BEId Bedbid { get; set; }
        public string  ReplaceTemplate { get; set; }
        public string NextExist { get; set; }
        public string SavePath
        {
            get
            {
                return _savepath;
            }
            set
            {
                if (value!=null && value!="")
                    if(!value.EndsWith("\\"))
                        value += "\\";
                _savepath = value;
            }
        }
        private string _savepath;
        public CaseCmd caseCmd { get; set; }
        public TableCmd tableCmd { get; set; }
        public TableValueCmd tablevalueCmd { get; set; }
        public List<TableCmd> ListTable { get; set; }
        public SubGapCmd subgapCmd { get; set; }
        public GapValueCmd gapvalueCmd { get; set; }
        public List<SubGapCmd> ListGap { get; set; }
        public bool DownLoadSuburl { get; set; }
        public string DownLoadSuburlType { get; set; }
        public bool DownLoadSuburlChangeUrl { get; set; }
        public bool DownLoadurl { get; set; }
        public string DownLoadurlType { get; set; }
        public bool DownLoadurlChangeUrl { get; set; }
        public bool bLocation { get; set; }
        public bool ModeAllTxt { get; set; }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder("{");
            foreach (KeyValuePair<string, string> a in cmdkeyvalue)
                sb.Append(a.Key + "=" + a.Value+"&");
            sb.Append("}");
            if(sb.ToString() == "{}")
               return "";
            return sb.ToString();
        }

    }
    public class CaseCmd
    {
        public CaseCmd(string str)
        {
            conditions = new List<Condition>();
            string[] items = str.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string s in items)
            {
                if(s.Contains("(") && s.Contains(")=>"))
                    conditions.Add(new Condition(s));
            }
        }
        public List<Condition> conditions;
    }
    public class Condition
    {
        public Condition(string strcdt)
        {
            strcdt = strcdt.Trim();
            int te = strcdt.IndexOf("(");
            int ve = strcdt.IndexOf(")=>");
            ctype = strcdt.Substring(0, te);
            cvalue = strcdt.Substring(te+1,ve-te-1);
            string actstr =  strcdt.Substring(ve+3);
            if (ctype == "contains")
                b = bc_contains;
            else if (ctype == "startswith")
            {
                b = bc_starswith;
            }
            else if (ctype == "endswith")
            {
                b = bc_Endswith;
            }
            else if (ctype == "equals")
            {
                b = bc_Equals;
            }
            else if (ctype == "default")
            {
                b =bc_default;
            }
            else 
            {
                b = bc_false;
            }

            if (actstr.Contains("N"))
            {
                actvalue = actstr;
                a = act_getNcompute;
            }else
            {
                if (actstr=="null" || DgvTools.ValidDoubleNumber(actstr))
                {
                    actvalue = actstr;
                    a = act_getactvalue;
                }
                else
                {
                    a = act_getSame;
                }
            } 
        }
        public bool bc_contains(string s)
        {
            return s.Contains(cvalue);
        }
        public bool bc_starswith(string s)
        {
            return s.StartsWith(cvalue);
        }
        public bool bc_Endswith(string s)
        {
            return s.EndsWith(cvalue);
        }
        public bool bc_Equals(string s)
        {
            return s.Equals(cvalue);
        }
        public bool bc_default(string s)
        {
            return true;
        }
        public bool bc_false(string s)
        {
            return false;
        }

        public string act_getnumber(string s)
        {//不能识别复杂数字
            StringBuilder number = new StringBuilder();
            bool bn = false;
            if (".-0123456789".Contains(s[0]))
            {
                bn = true;
            }
            foreach (char c in s)
            {
                if (".-0123456789".Contains(c))
                {
                    if (!bn) number.Clear();
                    else
                        number.Append(c);
                    bn = true;
                }
                else
                {
                    bn = false;
                }
            }
            return number.ToString();
        }
        public string act_getactvalue(string s)
        {
            return actvalue;
        }
        public string act_getNcompute(string s)
        {
            string N = act_getnumber(s);
            return actvalue.Replace("N", N);
        }
        public string act_getSame(string s)
        {
            return s;
        }
        public string ctype;
        public string cvalue;
        public string actvalue;
        public ActCondition a;
        public BoolCondition b;
    }
    public class TableCmd
    {
        public TableCmd(string str)
        {
            this.str = null;
            cols = null;
            string[] items = str.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string s in items)
            {
                if (s.Contains("name="))
                    Name = s.Substring(s.IndexOf("name=")+5).Trim();
                else if (s.Contains("rowgap="))
                    RowGag = s.Substring(s.IndexOf("rowgap=") + 7).Trim().Split('|');
                else if(s.Contains("colgap="))
                    ColGap = s.Substring(s.IndexOf("colgap=") + 7).Trim().Split('|');
                else if (s.Contains("location="))
                    Location = new BETags(s.Substring(s.IndexOf("location=") + 9).Trim());
            }
        }
        internal string Table(int RowIndex, int ColIndex)
        {          
            if (txt != null)
            {
                if (str == null || !string.ReferenceEquals(str,txt))
                {
                    str = txt;
                    string s = Location.Match(txt);
                    rows = s.Split(RowGag, StringSplitOptions.RemoveEmptyEntries);
                    cols = new string[rows.Length][];
                    
                }
                if (RowIndex < rows.Length)
                {
                    if (cols[RowIndex] == null)
                        cols[RowIndex] = rows[RowIndex]
                            .Split(ColGap, StringSplitOptions.RemoveEmptyEntries);
                    if (ColIndex < cols[RowIndex].Length)
                        return cols[RowIndex][ColIndex];
                }
            }
            return "";
        }
        public string Name { get; set; }
        public string[] RowGag { get; set; }
        public string[] ColGap { get; set; }
        public BETags Location { get; set; }
        private string[] rows;
        private string[][] cols;
        private string str;
        public  static string  txt;

    }

    public class TableValueCmd
    {
        private int RowIndex;
        private int ColIndex;
        public TableValueCmd(string str)
        {
            Valid = false;
            ColIndex = RowIndex = -1;
            string[] items = str.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string s in items)
            {
                if (s.Contains("name="))
                    Name = s.Substring(s.IndexOf("name=") +5).Trim();
                else if (s.Contains("rowindex="))
                    RowIndex = Convert.ToInt32(s.Substring(s.IndexOf("rowindex=") + 9));
                else if (s.Contains("colindex="))
                    ColIndex = Convert.ToInt32(s.IndexOf("colindex=") + s.Substring(9)); 
            }

        }

        internal void InitTable(List<TableCmd> listtable)
        {
            if(RowIndex >=0 && ColIndex >=0)
            foreach (TableCmd t in listtable)
                if (Name == t.Name)
                {
                    Tablecmd = t;
                    Valid = true;
                    break;
                }
        }
        public bool Valid { get; set; }
        public string Name { get; set; }
        public TableCmd Tablecmd { get; set; }

        internal string GetValue() //RowIndex,ColIndex必定 >=0
        {
            if(Tablecmd !=null ) 
                return Tablecmd.Table(RowIndex,ColIndex);
            return "";
        }
    }
    
    //////////////
    
    public class SubGapCmd
    {
        public SubGapCmd(string str)
        {
            this.str = null;
            cols = null;
            string[] items = str.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string s in items)
            {
                if (s.Contains("name="))
                    Name = s.Substring(s.IndexOf("name=")+5).Trim();              
                else if(s.Contains("gaptag=")){
                  string  strColGap = s.Substring(s.IndexOf("gaptag=") + 7).Trim();     
                  ColGap =   new BETag(strColGap);
                }
            }
        }
        internal string Table(int ColIndex)
        {          
            if (txt != null)
            {
                if (str == null || !string.ReferenceEquals(str,txt))
                {
                	str = txt;
                	cols = null;
                }
				if (cols == null){
					 List<string> lc = new List<string>();
					 BEPos bp = new BEPos(0, txt.Length, txt);
					 bp = ColGap.BEPos(bp);
					 while(bp.Valid()){
					 	lc.Add(bp.String);
					 	bp = ColGap.NextBEPos(bp);
					 }
					 cols = lc.ToArray();	
//					cols = txt.Split(ColGap, StringSplitOptions.RemoveEmptyEntries);
				}	
                if (ColIndex < cols.Length)
                    return cols[ColIndex];                
            }
            return "";
        }
        public string Name { get; set; }
        public BETag  ColGap { get; set; }
        private string[] cols;
        private string str;
        public  static string  txt;
    }
    public class GapValueCmd
    {
        private int ColIndex;
        public GapValueCmd(string str)
        {
            Valid = false;
            ColIndex = -1;
            string[] items = str.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string s in items)
            {
                if (s.Contains("name="))
                    Name = s.Substring(s.IndexOf("name=") +5).Trim();               
                else if (s.Contains("colindex="))
                    ColIndex = Convert.ToInt32(s.IndexOf("colindex=") + s.Substring(9)); 
            }

        }

        internal void InitSubGap(List<SubGapCmd> listgap)
        {
            if( ColIndex >=0)
            foreach (SubGapCmd t in listgap)
                if (Name == t.Name)
                {
                    Subgapcmd = t;
                    Valid = true;
                    break;
                }
        }
        public bool Valid { get; set; }
        public string Name { get; set; }
        public SubGapCmd Subgapcmd { get; set; }

        internal string GetValue() //RowIndex,ColIndex必定 >=0
        {
            if(Subgapcmd !=null ) 
                return Subgapcmd.Table(ColIndex);
            return "";
        }
    }
    
    
}